package com.hsurosy.trigger.http;

import com.alibaba.fastjson2.JSON;
import com.hsurosy.api.IRaffleActivityService;
import com.hsurosy.api.dto.*;
import com.hsurosy.domain.activity.model.entity.*;
import com.hsurosy.domain.activity.model.valobj.OrderTradeTypeVO;
import com.hsurosy.domain.activity.service.IRaffleActivityAccountQuotaService;
import com.hsurosy.domain.activity.service.IRaffleActivityPartakeService;
import com.hsurosy.domain.activity.service.IRaffleActivitySkuProductService;
import com.hsurosy.domain.activity.service.armory.IActivityArmory;
import com.hsurosy.domain.award.model.entity.UserAwardRecordEntity;
import com.hsurosy.domain.award.model.valobj.AwardStateVO;
import com.hsurosy.domain.award.service.IAwardService;
import com.hsurosy.domain.credit.model.entity.CreditAccountEntity;
import com.hsurosy.domain.credit.model.entity.TradeEntity;
import com.hsurosy.domain.credit.model.valobj.TradeNameVO;
import com.hsurosy.domain.credit.model.valobj.TradeTypeVO;
import com.hsurosy.domain.credit.service.ICreditAdjustService;
import com.hsurosy.domain.rebate.model.entity.BehaviorEntity;
import com.hsurosy.domain.rebate.model.entity.BehaviorRebateOrderEntity;
import com.hsurosy.domain.rebate.model.entity.TaskEntity;
import com.hsurosy.domain.rebate.model.valobj.BehaviorTypeVO;
import com.hsurosy.domain.rebate.service.IBehaviorRebateService;
import com.hsurosy.domain.strategy.model.entity.RaffleAwardEntity;
import com.hsurosy.domain.strategy.model.entity.RaffleFactorEntity;
import com.hsurosy.domain.strategy.service.IRaffleStrategy;
import com.hsurosy.domain.strategy.service.armory.IStrategyArmory;
import com.hsurosy.types.enums.ResponseCode;
import com.hsurosy.types.exception.AppException;
import com.hsurosy.types.model.Response;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author Hsu琛君珩
 * @Date 2024-11-15 16:22
 * @Description 抽奖活动服务
 * @Version: v1.0.0
 */
@Slf4j
@RestController()
@CrossOrigin("${app.config.cross-origin}")
@RequestMapping("/api/${app.config.api-version}/raffle/activity")
public class RaffleActivityController implements IRaffleActivityService {

    private final SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyyMMdd"); // 日期格式化工具，用于格式化为 "yyyyMMdd" 格式的日期字符串

    @Resource
    private IActivityArmory activityArmory; // 活动装配服务
    @Resource
    private IStrategyArmory strategyArmory; // 策略装配服务
    @Resource
    private IRaffleActivityPartakeService raffleActivityPartakeService; // 活动参与服务
    @Resource
    private IRaffleStrategy raffleStrategy; // 抽奖策略服务
    @Resource
    private IAwardService awardService; // 奖品服务
    @Resource
    private IBehaviorRebateService behaviorRebateService; // 行为返利服务
    @Resource
    private IRaffleActivityAccountQuotaService raffleActivityAccountQuotaService; // 活动账户配额服务
    @Resource
    private ICreditAdjustService creditAdjustService; // 积分调整服务
    @Resource
    private IRaffleActivitySkuProductService raffleActivitySkuProductService; // 活动SKU商品服务

    /**
     * 活动装配 - 数据预热 / 把活动配置的对应的 SKU 一起装配
     *
     * @param activityId 活动ID
     * @return 装配结果
     * <p>
     * 接口：<a href="http://localhost:8091/api/v1/raffle/activity/armory">/api/v1/raffle/activity/armory</a>
     * 入参：{"activityId":100001,"userId":"xiaofuge"}
     * curl --request GET \
     *      --url 'http://localhost:8091/api/v1/raffle/activity/armory?activityId=100301'
     */
    @GetMapping(value = "/armory")
    @Override
    public Response<Boolean> armory(@RequestParam Long activityId) {
        try {
            log.info("活动装配，数据预热，开始 activityId: {}", activityId);
            // 1. 活动装配（预热 SKU 数据）
            activityArmory.assembleActivitySkuByActivityId(activityId);
            // 2. 策略装配（预热抽奖策略数据）
            strategyArmory.assembleLotteryStrategyByActivityId(activityId);
            // 3. 返回成功响应
            Response<Boolean> response = Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(true)
                    .build();
            log.info("活动装配，数据预热，完成 activityId: {}", activityId);
            return response;
        } catch (Exception e) {
            log.error("活动装配，数据预热，失败 activityId: {}", activityId, e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 抽奖接口
     *
     * @param request 请求对象
     * @return 抽奖结果
     * 接口：<a href="http://localhost:8091/api/v1/raffle/activity/draw">/api/v1/raffle/activity/draw</a>
     * 入参：{"activityId":100001,"userId":"hsurosy"}
     * curl --request POST \
     *      --url http://localhost:8091/api/v1/raffle/activity/draw \
     *      --header 'content-type: application/json' \
     *      --data '{
     *          "userId":"xiaofuge",
     *          "activityId": 100301
     *      }'
     */
    @PostMapping("/draw")
    @Override
    public Response<ActivityDrawResponseDTO> draw(@RequestBody ActivityDrawRequestDTO request) {
        try {
            log.info("活动抽奖开始 userId: {} activityId: {}", request.getUserId(), request.getActivityId());
            // 1. 参数校验
            if (StringUtils.isBlank(request.getUserId()) || null == request.getActivityId()) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }

            // 2. 参与活动 - 创建参与记录订单
            UserRaffleOrderEntity userRaffleOrderEntity = raffleActivityPartakeService.createOrder(request.getUserId(), request.getActivityId());
            log.info("活动抽奖，创建订单 userId: {} activityId: {} orderId: {}", request.getUserId(), request.getActivityId(), userRaffleOrderEntity.getOrderId());

            // 3. 抽奖策略 - 执行抽奖
            RaffleAwardEntity raffleAwardEntity = raffleStrategy.performRaffle(RaffleFactorEntity.builder()
                    .userId(userRaffleOrderEntity.getUserId())
                    .strategyId(userRaffleOrderEntity.getStrategyId())
                    .endDateTime(userRaffleOrderEntity.getEndDateTime())
                    .build());

            // 4. 存放结果 - 写入中奖记录
            UserAwardRecordEntity userAwardRecordEntity = UserAwardRecordEntity.builder()
                    .userId(userRaffleOrderEntity.getUserId())
                    .activityId(userRaffleOrderEntity.getActivityId())
                    .strategyId(userRaffleOrderEntity.getStrategyId())
                    .orderId(userRaffleOrderEntity.getOrderId())
                    .awardId(raffleAwardEntity.getAwardId())
                    .awardTitle(raffleAwardEntity.getAwardTitle())
                    .awardTime(new Date())
                    .awardState(AwardStateVO.create)
                    .awardConfig(raffleAwardEntity.getAwardConfig())
                    .build();
            awardService.saveUserAwardRecord(userAwardRecordEntity);

            // 5. 返回抽奖结果
            return Response.<ActivityDrawResponseDTO>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(ActivityDrawResponseDTO.builder()
                            .awardId(raffleAwardEntity.getAwardId())
                            .awardTitle(raffleAwardEntity.getAwardTitle())
                            .awardIndex(raffleAwardEntity.getSort())
                            .build())
                    .build();
        } catch (AppException e) {
            // 业务异常处理
            log.error("活动抽奖失败 userId: {} activityId: {}", request.getUserId(), request.getActivityId(), e);
            return Response.<ActivityDrawResponseDTO>builder()
                    .code(e.getCode())
                    .info(e.getInfo())
                    .build();
        } catch (Exception e) {
            // 未知异常处理
            log.error("活动抽奖失败 userId: {} activityId: {}", request.getUserId(), request.getActivityId(), e);
            return Response.<ActivityDrawResponseDTO>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 日历签到返利接口
     *
     * @param userId 用户ID
     * @return 签到返利结果
     * <p>
     * 接口：<a href="http://localhost:8091/api/v1/raffle/activity/calendar_sign_rebate">/api/v1/raffle/activity/calendar_sign_rebate</a>
     * 入参：xiaofuge
     * <p>
     * curl -X POST http://localhost:8091/api/v1/raffle/activity/calendar_sign_rebate -d "userId=xiaofuge" -H "Content-Type: application/x-www-form-urlencoded"
     */
    @PostMapping("/calendar_sign_rebate")
    @Override
    public Response<Boolean> calendarSignRebate(@RequestParam String userId) {
        try {
            // 日志记录：开始日历签到返利
            log.info("日历签到返利开始 userId: {}", userId);
            // 构建行为实体对象
            BehaviorEntity behaviorEntity = new BehaviorEntity();
            behaviorEntity.setUserId(userId); // 设置用户ID
            behaviorEntity.setBehaviorTypeVO(BehaviorTypeVO.SIGN); // 设置行为类型为签到
            behaviorEntity.setOutBusinessNo(dateFormatDay.format(new Date())); // 记录当前日期作为外部业务编号

            // 调用返利服务生成订单
            List<String> orderIds = behaviorRebateService.createOrder(behaviorEntity);
            log.info("日历签到返利完成 userId: {} orderIds: {}", userId, JSON.toJSONString(orderIds));
            // 返回成功响应
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(true)
                    .build();
        } catch (AppException e) {
            // 日志记录：发生应用异常
            log.error("日历签到返利异常 userId: {}", userId, e);
            // 返回应用异常的响应
            return Response.<Boolean>builder()
                    .code(e.getCode())
                    .info(e.getInfo())
                    .build();
        } catch (Exception e) {
            // 日志记录：发生系统异常
            log.error("日历签到返利失败 userId: {}", userId, e);
            // 返回系统异常的响应
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
    }

    /**
     * 检查用户是否完成了日历签到返利
     *
     * @param userId 用户ID
     * @return 是否已完成签到返利的响应
     * <p>
     * 接口：<a href="http://localhost:8091/api/v1/raffle/activity/is_calendar_sign_rebate">/api/v1/raffle/activity/is_calendar_sign_rebate</a>
     * 入参：用户ID
     * <p>
     * curl -X POST http://localhost:8091/api/v1/raffle/activity/is_calendar_sign_rebate -d "userId=xiaofuge" -H "Content-Type: application/x-www-form-urlencoded"
     */
    @PostMapping(value = "/is_calendar_sign_rebate")
    @Override
    public Response<Boolean> isCalendarSignRebate(@RequestParam String userId) {
        try {
            log.info("查询用户是否完成日历签到返利开始 userId: {}", userId);
            // 构造业务流水号，以当前日期为标识
            String outBusinessNo = dateFormatDay.format(new Date());
            // 查询用户在指定日期的签到返利记录
            List<BehaviorRebateOrderEntity> behaviorRebateOrderEntities = behaviorRebateService.queryOrderByOutBusinessNo(userId, outBusinessNo);
            log.info("查询用户是否完成日历签到返利完成 userId: {} orders.size: {}", userId, behaviorRebateOrderEntities.size());
            // 返回签到结果
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(!behaviorRebateOrderEntities.isEmpty()) // 如果返利记录存在，则表示已完成
                    .build();
        } catch (Exception e) {
            log.error("查询用户是否完成日历签到返利失败 userId: {}", userId, e);
            // 异常处理，返回失败结果
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
    }

    /**
     * 查询用户活动账户信息
     *
     * @param request 包含用户ID和活动ID的请求对象
     * @return 用户活动账户信息的响应
     * <p>
     * 接口：<a href="http://localhost:8091/api/v1/raffle/activity/query_user_activity_account">/api/v1/raffle/activity/query_user_activity_account</a>
     * 入参：用户ID和活动ID
     * <p>
     * curl -X POST http://localhost:8091/api/v1/raffle/activity/query_user_activity_account \
     *      -H "Content-Type: application/json" \
     *      -d '{"userId":"xiaofuge", "activityId":100301}'
     */
    @PostMapping("/query_user_activity_account")
    @Override
    public Response<UserActivityAccountResponseDTO> queryUserActivityAccount(@RequestBody UserActivityAccountRequestDTO request) {
        try {
            log.info("查询用户活动账户开始 userId: {}, activityId: {}", request.getUserId(), request.getActivityId());
            // 参数校验，确保用户ID和活动ID不为空
            if (StringUtils.isBlank(request.getUserId()) || null == request.getActivityId()) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            // 查询用户的活动账户信息
            ActivityAccountEntity activityAccountEntity = raffleActivityAccountQuotaService.queryActivityAccountEntity(request.getActivityId(), request.getUserId());
            // 构建返回对象
            UserActivityAccountResponseDTO userActivityAccountResponseDTO = new UserActivityAccountResponseDTO();
            userActivityAccountResponseDTO.setTotalCount(activityAccountEntity.getTotalCount());
            userActivityAccountResponseDTO.setTotalCountSurplus(activityAccountEntity.getTotalCountSurplus());
            userActivityAccountResponseDTO.setDayCount(activityAccountEntity.getDayCount());
            userActivityAccountResponseDTO.setDayCountSurplus(activityAccountEntity.getDayCountSurplus());
            userActivityAccountResponseDTO.setMonthCount(activityAccountEntity.getMonthCount());
            userActivityAccountResponseDTO.setMonthCountSurplus(activityAccountEntity.getMonthCountSurplus());
            log.info("查询用户活动账户完成 userId: {}, activityId: {}, dto: {}", request.getUserId(), request.getActivityId(), JSON.toJSONString(userActivityAccountResponseDTO));
            // 返回账户信息
            return Response.<UserActivityAccountResponseDTO>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(userActivityAccountResponseDTO)
                    .build();
        } catch (Exception e) {
            log.error("查询用户活动账户失败 userId: {}, activityId: {}", request.getUserId(), request.getActivityId(), e);
            // 异常处理，返回失败结果
            return Response.<UserActivityAccountResponseDTO>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 查询活动下的SKU商品列表
     *
     * @param activityId 活动ID，用于标识某一具体的活动
     * @return 包含SKU商品信息列表的响应对象
     */
    @PostMapping(value = "/query_sku_product_list_by_activity_id")
    @Override
    public Response<List<SkuProductResponseDTO>> querySkuProductListByActivityId(Long activityId) {
        try {
            log.info("查询sku商品集合开始 activityId: {}", activityId);
            // 1. 参数校验，确保 activityId 不为空
            if (null == activityId) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }

            // 2. 调用服务查询活动下的 SKU 商品实体列表
            List<SkuProductEntity> skuProductEntities = raffleActivitySkuProductService.querySkuProductEntityListByActivityId(activityId);

            // 3. 构造返回的 SKU 商品响应 DTO 列表
            List<SkuProductResponseDTO> skuProductResponseDTOS = new ArrayList<>(skuProductEntities.size());
            for (SkuProductEntity skuProductEntity : skuProductEntities) {
                // 转换商品计数信息
                SkuProductResponseDTO.ActivityCount activityCount = new SkuProductResponseDTO.ActivityCount();
                activityCount.setTotalCount(skuProductEntity.getActivityCount().getTotalCount());
                activityCount.setDayCount(skuProductEntity.getActivityCount().getDayCount());
                activityCount.setMonthCount(skuProductEntity.getActivityCount().getMonthCount());

                // 转换商品信息
                SkuProductResponseDTO skuProductResponseDTO = new SkuProductResponseDTO();
                skuProductResponseDTO.setSku(skuProductEntity.getSku());
                skuProductResponseDTO.setActivityId(skuProductEntity.getActivityId());
                skuProductResponseDTO.setActivityCountId(skuProductEntity.getActivityCountId());
                skuProductResponseDTO.setStockCount(skuProductEntity.getStockCount());
                skuProductResponseDTO.setStockCountSurplus(skuProductEntity.getStockCountSurplus());
                skuProductResponseDTO.setProductAmount(skuProductEntity.getProductAmount());
                skuProductResponseDTO.setActivityCount(activityCount);

                skuProductResponseDTOS.add(skuProductResponseDTO);
            }

            log.info("查询sku商品集合完成 activityId: {} skuProductResponseDTOS: {}", activityId, JSON.toJSONString(skuProductResponseDTOS));
            return Response.<List<SkuProductResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(skuProductResponseDTOS)
                    .build();
        } catch (Exception e) {
            log.error("查询sku商品集合失败 activityId: {}", activityId, e);
            return Response.<List<SkuProductResponseDTO>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 查询用户积分账户的当前积分值
     *
     * @param userId 用户ID，用于标识需要查询积分账户的用户
     * @return 包含用户当前积分值的响应对象
     */
    @PostMapping("/query_user_credit_account")
    @Override
    public Response<BigDecimal> queryUserCreditAccount(String userId) {
        try {
            log.info("查询用户积分值开始 userId: {}", userId);
            // 调用积分调整服务查询用户积分账户信息
            CreditAccountEntity creditAccountEntity = creditAdjustService.queryUserCreditAccount(userId);
            log.info("查询用户积分值完成 userId: {} adjustAmount: {}", userId, creditAccountEntity.getAdjustAmount());
            // 构造并返回成功响应对象
            return Response.<BigDecimal>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(creditAccountEntity.getAdjustAmount())  // 返回用户当前积分值
                    .build();
        } catch (Exception e) {
            log.info("查询用户积分值失败 userId: {}", userId, e);
            return Response.<BigDecimal>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 积分兑换商品操作
     *
     * @param request 积分兑换请求对象，包含用户ID和商品SKU
     * @return 返回操作结果的响应对象
     */
    @PostMapping("/credit_pay_exchange_sku")
    @Override
    public Response<Boolean> creditPayExchangeSku(@RequestBody SkuProductShopCartRequestDTO request) {
        try {
            log.info("积分兑换商品开始 userId: {} sku: {}", request.getUserId(), request.getSku());

            // 1. 创建未支付活动订单
            UnpaidActivityOrderEntity unpaidActivityOrder = raffleActivityAccountQuotaService.createOrder(SkuRechargeEntity.builder()
                    .userId(request.getUserId())
                    .sku(request.getSku())
                    .outBusinessNo(RandomStringUtils.randomNumeric(12))
                    .orderTradeType(OrderTradeTypeVO.credit_pay_trade)
                    .build());
            log.info("积分兑换商品，创建订单完成 userId: {} sku: {} outBusinessNo: {}", request.getUserId(), request.getSku(), unpaidActivityOrder.getOutBusinessNo());

            // 2. 使用积分支付订单
            String orderId = creditAdjustService.createOrder(TradeEntity.builder()
                    .userId(unpaidActivityOrder.getUserId())
                    .tradeName(TradeNameVO.CONVERT_SKU)
                    .tradeType(TradeTypeVO.REVERSE)
                    .amount(unpaidActivityOrder.getPayAmount().negate()) // 将支付金额变成负数
                    .outBusinessNo(unpaidActivityOrder.getOutBusinessNo())
                    .build());
            log.info("积分兑换商品，支付订单完成  userId: {} sku: {} orderId: {}", request.getUserId(), request.getSku(), orderId);

            // 3. 返回成功响应
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(true)
                    .build();
        } catch (AppException e) {
            log.error("积分兑换商品失败 userId: {} activityId: {}", request.getUserId(), request.getSku(), e);
            return Response.<Boolean>builder()
                    .code(e.getCode())
                    .info(e.getInfo())
                    .build();
        } catch (Exception e) {
            log.error("积分兑换商品失败 userId: {} sku: {}", request.getUserId(), request.getSku(), e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false)
                    .build();
        }
    }

}
